home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 011 / chgpath.arc / CHGPATH.C next >
Encoding:
C/C++ Source or Header  |  1987-04-06  |  10.7 KB  |  433 lines

  1. /*
  2.      Copyright (C) 1987 by Scott Mason, except where noted in the 
  3.        source code,  All Rights Reserved.
  4.  
  5.      Permission is hereby granted for use by non-profit entities only.
  6.      Distribution of this file, CHGPATH.EXE, and/or CHGPATH.DOC in any form
  7.      for a fee is prohibited.
  8.  
  9.      Written by Scott Mason
  10.                 4050 Jay Em Circle
  11.                 Ellicott City, MD  21043
  12.  
  13.      Written using the DeSmet C88 C compiler package, v2.51
  14.   
  15.      Acknowledgement and graditude is hereby given to:
  16.  
  17.          John M Sellens,
  18.                     who wrote the getpath & parse_path functions, and
  19.          Dan Lewis,
  20.                     who wrote the execute_string (and subsequent)
  21.                     functions, obtained from a file called SETVAR.C.
  22.      ------------------------------------------------------------------
  23.  
  24.  
  25.      Purpose:  Allows you the make permanent changes to the PATH
  26.  
  27.  
  28.                environment string from the DOS command line without
  29.  
  30.  
  31.                having to retype the entire PATH command string.
  32.  
  33.  
  34.   
  35. */   
  36.  
  37.  
  38.  
  39. #include <stdio.h>
  40.  
  41. char newpath[200] = "PATH ";
  42. char *np = newpath;
  43. char *cp;
  44. typedef char *char_ptr;
  45. char *get_path();
  46. char_ptr  *parse_path();
  47. char *copyright  = " Copyright (C) 1987 by Scott Mason, except where noted\n";
  48. char *copyright2 = " in the source code,  All Rights Reserved.\n";
  49.  
  50. main(argc,argv)
  51. int argc;
  52. char **argv;
  53. {
  54.     int i;
  55.  
  56.     if (argc != 2)
  57.         usage();
  58.  
  59.     cp = get_path();        /* get the PATH environment string */
  60.  
  61.     argv++;
  62.     if (**argv == '+')
  63.         addpath(++*argv);
  64.     else if (**argv == '-')
  65.         delpath(++*argv);
  66.     else
  67.         usage();
  68.  
  69. }    /* end main */
  70.  
  71.  
  72. addpath(p)
  73. char *p;
  74. {
  75.  
  76.     strcat(np,cp);   /* concat current path setting onto newpath */
  77.     strcat(np,";");
  78.     strcat(np,p);   /* concat the path to add onto newpath */
  79.     execute_string(np);
  80.     printf("%s\n",np);
  81.  
  82. }    /* end addpath */
  83.  
  84.  
  85. delpath(p)
  86. char *p;
  87. {
  88.     int i, j;
  89.     char_ptr *paths;
  90.     char *s;
  91.  
  92.     s = p;
  93.     while (*s)                /* convert path to delete to upper case */
  94.     {
  95.         if (isalpha(*s))
  96.             *s = toupper(*s);
  97.         s++;
  98.     }
  99.  
  100.     paths = parse_path(cp);
  101.     if (paths != NULL)
  102.     {
  103.         for (i=0; paths[i]!=NULL; i++)
  104.         {                             /* compare with the path to delete */
  105.            if (strlen(p) != (j=strlen(paths[i])) ||  /* beats DeSmet strncmp bug */
  106.                      strncmp(p,paths[i],j)) 
  107.             {
  108.                 strcat(np,paths[i]);         /* if not ==, concat that path onto */
  109.                 strcat(np,";");        /*  the newpath string */
  110.             }
  111.         }
  112.         *(p = rindex(np,';')) = '\0';    /* get rid of that last ; */
  113.         execute_string(np);
  114.         printf("%s\n",np);
  115.     }
  116.     else
  117.         printf("No path is set ...\n");
  118.  
  119. }    /* end delpath */
  120.  
  121.  
  122. usage()
  123. {
  124.     puts("\nUsage:  CHGPATH  +newpath\n");
  125.     puts("            to Add newpath to the current path setting\n");
  126.     puts("        CHGPATH  -oldpath\n");
  127.     puts("            to Remove oldpath from the current path setting\n\n");
  128.     puts("    Where newpath & oldpath must be valid paths.\n\n");
  129.     exit(1);
  130.  
  131. }    /* end usage */
  132.  
  133.  
  134. /**********************************************************************/
  135.  
  136.  
  137. /* The following are two routines to make it easier to access the
  138.    PATH environment variable.  They are written for use with the
  139.    DeSmet C Compiler.  Known portability problems:
  140.  
  141.                 - assembler code embedded in the C code
  142.                 - requires that code segment register (CS) be set to the
  143.                   same value as at program invocation so that the
  144.                   program segment prefix can be located.  This would
  145.                   probably only be a problem if a "large model"
  146.                   compiler is used.
  147.  
  148.         The code is a little kludgy in places but...
  149.         Any suggestions for improvements gratefully accepted.
  150. */
  151.  
  152. /*   Written by John M Sellens, April, 1984
  153.      (c) Copyright 1984 John M Sellens
  154.  
  155. Permission is granted to use, distribute and/or modify this code unless
  156. done for direct commercial profit.  If you find these routines useful,
  157. modest contributions (monetary or otherwise) will be gratefully accepted.
  158. Author's name, address and this notice must be included in any copies.
  159. */
  160.  
  161. char_ptr *parse_path(ps)
  162. char *ps;
  163. {
  164.         /* Takes the path string returned by get_path and  destroys it,
  165.            by inserting NULL's and returning an array of pointers to
  166.            characters that point to locations in the original path
  167.            string.  The pointer after the last pointer into the path
  168.            string is NULL.  If the path string is NULL, then NULL is
  169.            returned.
  170.         */
  171.  
  172.         int i, j, num;
  173.         char_ptr *pa;
  174.  
  175.         if (ps[0] == '\0')      /* no path */
  176.             return(NULL);
  177.  
  178.         /* count the number of semi-colons, add 1 = number of paths */
  179.  
  180.         for (num=1, i=0; ps[i] != '\0'; i++)
  181.             if (ps[i] == ';')
  182.                  num++;
  183.  
  184.         pa = (char_ptr *)malloc(sizeof(char_ptr) * (num+1));
  185.         pa[num] = NULL;
  186.  
  187.         /* now loop through and point to each path */
  188.  
  189.         for (i=j=0; i<num; i++) 
  190.         {
  191.             pa[i] = &ps[j];
  192.             while(ps[j]!=';' && ps[j]!='\0')
  193.                 j++;
  194.             ps[j++] = '\0';
  195.         }
  196.  
  197.         return(pa);
  198. }
  199.  
  200.  
  201.  
  202. char *get_path()
  203. {
  204.         /* Returns a pointer to a string containing the value of
  205.            the environment variable PATH.  E.g. if PATH=A:\;B:\
  206.            the string "A:\;B:\" is returned.  If no PATH is set,
  207.            an empty string is returned.
  208.         */
  209.  
  210.         static int path_seg;
  211.  
  212.         /* these three declarations must be first so that they can be
  213.            referred to by stack address near the end when copying
  214.            the PATH variable */
  215.  
  216.         char *base, *path;
  217.         int siz;
  218.         char *next;
  219.         char env_str[10];       /* leave a little extra space just in case */
  220.         int i, done;
  221.  
  222. #asm
  223.  
  224. ;               determine the segment that the environment starts at
  225. ;               this requires that cs is set to the same value as at
  226. ;               program entry i.e. 100H past the program segment prefix
  227.  
  228.                 push es
  229.                 mov ax,cs
  230.                 sbb ax,10h
  231.                 mov es,ax
  232.                 mov ax,es:[2cH]
  233.                 pop es
  234.                 mov word get_path_path_seg_,ax
  235. #end
  236.  
  237.         /* look for the start of PATH= */
  238.         /* there's always going to be at least one thing in environment */
  239.  
  240.         done = FALSE;
  241.         next = 0;
  242.         env_str[0] = '\0';
  243.         while ((strncmp("PATH=",env_str,5) != 0) && !done) 
  244.         {
  245.             base = next;
  246.  
  247.             /* set DS to path_seg */
  248.  
  249. #asm
  250.             push ds
  251.             mov ds,word get_path_path_seg_
  252.  
  253. #end
  254.  
  255.             if (base[0] == '\0')
  256.                 done = TRUE;    /* no more variables to look at */
  257.  
  258.             else
  259.             {        /* now copy 5 characters into memory */
  260.                 for (i=0; i<5; i++)
  261.                      env_str[i] = base[i];   /* ok since env_str is on stack */
  262.  
  263.                         /* now set next to first character after end of this string */
  264.  
  265.                 while ((next++)[0] != '\0')
  266.                          ;
  267.             }
  268.                 /* reset DS */
  269. #asm
  270.             pop ds
  271. #end
  272.  
  273.         }
  274.         if (done) {     /* no PATH environment variable set */
  275.             path = (char *)malloc(1);
  276.             path[0] = '\0';
  277.         } else {
  278.             siz = next - base - 5;
  279.             path = (char *)malloc(siz);
  280.             base += 5;      /* skip over 'PATH=' */
  281.                          /* copy the PATH string to path */
  282. #asm
  283.             push cx
  284.             push es
  285.             push ds
  286.             mov cx,ds
  287.             mov es,cx
  288.             mov ds,word get_path_path_seg_
  289.             mov si,word [bp-2]      ;base
  290.             mov di,word [bp-4]      ;path
  291.             mov cx,word [bp-6]      ;siz
  292.             rep movsb
  293.             pop ds
  294.             pop es
  295.             pop cx
  296. #end
  297.         }
  298.         return(path);
  299.  
  300. }
  301. /******************************************************************/
  302. /*
  303.     The following little program can set an environment variable
  304.     whose name is the first command line argument, and whose new
  305.     value is the second command line argument.  For example, to
  306.     set environment variable XYZ to a value of HELLO, you would
  307.     run this program using the command SETVAR XYZ HELLO.
  308.  
  309.     The *PURPOSE* of this piece of code is to illustrate an un-
  310.     documented DOS interrupt entry point (2Eh) that will execute
  311.     *ANY* DOS command *WITHOUT* having to load another copy of
  312.     COMMAND.COM.  Not only is it faster, but it is the ONLY way
  313.     to set an environment variable (short of peeking and poking
  314.     around into memory).  You *CAN'T* set an environment variable
  315.     with the command exec("COMMAND.COM", "/CSETXYZ=HELLO") because
  316.     when the second copy of COMMAND.COM is loaded, it gets its
  317.     very own environment (a duplicate of the parent's).  Although
  318.     the SET command WILL modify that duplicate copy, it won't
  319.     modify the parent's!
  320.  
  321.     When I said that interrupt 2Eh can be used to execute *ANY*
  322.     DOS command, I meant just that!  You can leave off the filename
  323.     extension (as you normally do at the command line), and it will
  324.     perform the normal search for COM, EXE, and BAT files to execute,
  325.     or even execute built-in commands as we've seen above.
  326.  
  327.     Enjoy!
  328.  
  329.     Dan Lewis, owner
  330.     Key Software Products
  331.     440 Ninth Avenue
  332.     Menlo Park, CA 94025
  333.     (415) 364-9847
  334.  
  335. */
  336.  
  337. Execute_String(s)
  338. char *s;
  339. {
  340.     long vec22, vec23, vec24 ;
  341.     long Get_Vec() ;
  342.     static char bfr[81];
  343.  
  344.     strcpy(bfr + 1,s) ;
  345.     *bfr = strlen(bfr + 1) ;
  346.     strcat(bfr + 1,"\r") ;
  347.  
  348.     /* preserve cntrl-break, terminate, and critical error vectors */
  349.     vec22 = Get_Vec(0x22) ;
  350.     vec23 = Get_Vec(0x23) ;
  351.     vec24 = Get_Vec(0x24) ;
  352.  
  353.     Release_Memory() ;
  354.     Exec(bfr) ;    /* execute command */
  355.  
  356.     /* reset cntrl-break, terminate, and critical error vectors */
  357.     Set_Vec(0x22,vec22) ;
  358.     Set_Vec(0x23,vec23) ;
  359.     Set_Vec(0x24,vec24) ;
  360.     }
  361.  
  362. Exec(s)
  363. char *s ;
  364. {
  365. #asm
  366.     push    ds
  367.     push    bp
  368.     mov    cs:WORD save_ss,ss
  369.     mov    cs:WORD save_sp,sp
  370.     mov    si,[bp+4]
  371.     int    2Eh
  372.     mov    ss,cs:WORD save_ss
  373.     mov    sp,cs:WORD save_sp
  374.     pop    bp
  375.     pop    ds
  376.     jmp    Rtn
  377.  
  378. save_ss:dw    0
  379. save_sp:dw    0
  380. save_ds:dw    0
  381. save_bp:dw    0
  382.  
  383. Rtn:
  384. #end
  385. }
  386.  
  387.  
  388. Release_Memory()
  389. {
  390.     if (Release())
  391.     {
  392.         puts("Release Memory Failure\n") ;
  393.         exit(1) ;
  394.     }
  395. }
  396.  
  397.  
  398. Release()
  399. {
  400. #asm
  401.     mov    ax,cs
  402.     sub    ax,0010h
  403.     mov    es,ax
  404.     mov    bx,ds
  405.     add    bx,1000h
  406.     sub    bx,ax
  407.     mov    ah,4Ah
  408.     int    21h
  409.     mov    ax,0
  410.     jnc    R_Rtn
  411.     inc    ax
  412. R_Rtn:
  413. #end
  414. }
  415.  
  416.  
  417. long Get_Vec(vector)
  418. unsigned vector ;
  419. {
  420. #asm
  421.     mov    ah,35h
  422.     mov    al,BYTE [bp+4]
  423.     int    21h
  424.     mov    ax,bx
  425.     mov    dx,es
  426. #end
  427. }
  428.  
  429.  
  430. Set_Vec(vector,addr)
  431. unsigned vector ;
  432. long addr ;
  433. {
  434. #asm
  435.     mov    ah,25h
  436.     mov    al,BYTE [bp+4]
  437.     mov    bx,WORD [bp+6]
  438.     mov    es,WORD [bp+8]
  439.     int    21h
  440. #end
  441. }
  442.  
  443.